#pragma once
#include "StringUtil.h"

#define WM_COMM_BREAK_DETECTED  WM_USER+1 // A break was detected on input.
#define WM_COMM_CTS_DETECTED  WM_USER+2 // The CTS (clear-to-send) signal changed state.
#define WM_COMM_DSR_DETECTED  WM_USER+3 // The DSR (data-set-ready) signal changed state.
#define WM_COMM_ERR_DETECTED  WM_USER+4 // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
#define WM_COMM_RING_DETECTED  WM_USER+5 // A ring indicator was detected.
#define WM_COMM_RLSD_DETECTED  WM_USER+6 // The RLSD (receive-line-signal-detect) signal changed state.
#define WM_COMM_RXFLAG_DETECTED  WM_USER+7 // The event character was received and placed in the input buffer.
#define WM_COMM_TXEMPTY_DETECTED WM_USER+8 // The last character in the output buffer was sent.

#define WM_COMM_REVDATA    WM_USER+9 // A character was received and placed in the input buffer.

struct CReadData {
	DWORD size;
	char revBuff[BUF_LEN];

	CReadData::CReadData() {
		size = 0;
		memset(revBuff, 0, BUF_LEN);
	}
};

class CSerialCom
{
public:
	// contruction and destruction
	CSerialCom();
	virtual ~CSerialCom();
	void ClosePort();

	DCB GetDCB();
	HANDLE m_hComm;

	BOOL  InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 9600, CHAR parity = 'N', UINT databits = 8,
		UINT stopbits = 1, DWORD dwCommEvents = EV_RXCHAR, UINT writebuffersize = BUF_LEN);
	BOOL StartMonitoring();
	BOOL RestartMonitoring();
	BOOL StopMonitoring();
	DWORD GetWriteBufferSize();
	DWORD GetCommEvents();
	void WriteToPort(char* string);
	void WriteToPort(char* string, int n);
	void WriteToPort(LPCTSTR string);
	void WriteToPort(LPCTSTR string, int n);
	void EnumerateSerialPorts(CUIntArray& ports);
	void ProcessErrorMessage(wchar_t* ErrorText);

	// protected memberfunctions
	static UINT CommThread(LPVOID pParam);
	static void ReceiveChar(CSerialCom* port, COMSTAT comstat);
	static void WriteChar(CSerialCom* port);

	// owner window
	CWnd* m_pOwner;
	UINT m_nPortNr;
	// structures
	DCB m_dcb;
	OVERLAPPED m_ov;
	COMMTIMEOUTS m_CommTimeouts;
	// handles
	HANDLE m_hWriteEvent;
	HANDLE m_hShutdownEvent;
	HANDLE m_hEventArray[3];
	// misc
	char* m_szWriteBuffer;
	DWORD m_dwCommEvents;
	DWORD m_nWriteBufferSize;
	size_t m_nWriteSize;

	// synchronisation objects
	// thread
	BOOL m_bThreadAlive;
	CWinThread* m_Thread;
	CRITICAL_SECTION m_csCommunicationSync;
};

